/*
 * Javasript based on Functions(JBF) v1.03
 * 
 * Copyright(c) 2010, Fooxee (JA86.CN)
 *
 * JBF is licensed under the terms of the Open Source GPL 3.0(http://www.gnu.org/licenses/gpl.html) license. 
 * 
 * JBF's blog: http://www.cnblogs.com/JBF/
 * 
 * JBF's project: http://jbfproject.googlecode.com/
 *
 * Created by Fooxee. at 2010.03.30  mailTo:hjccjun@163.com
 */﻿
 
JBF.DomQuery={};
JBF.DomQuery.fn={
	//构造函数
	init:function()
	{
		
	},
	find_count:-1,
	find:function(selector,context,setdoc)
	{
		this.find_count++;
		if(this.find_count==0 || setdoc)
			context = context || window.document;

		if(context.nodeType==9 || JBF.isArray(context))
		{}
		else
			return [];
		if(selector.nodeType)
			return [nodeType];
		
		if(typeof selector == 'string' && !JBF.isEmpty(this.trim(selector)) )
		{
			var part=selector.split(/\s|\>|\<\+|\-|,/),
				oriselector=selector,
				ts=part[0],
				fc=selector.charAt(0),
				mc=selector.substr(ts.length,1);
				result=[],
				tarr=[];
			
			if(JBF.isArray(context))
			{
				tarr=context;
			}
			else
			JBF.each(context.getElementsByTagName('*'),function(n)
			{
				if(n && n.nodeType==1)
					tarr.push(n);
			});
			
			if(fc=='#')
			{
				var tsp=ts.split(/\:/);
				result=this.byId(tarr,tsp[0].replace('#',''));
				if(tsp[1])
				{
					result=this.filter(result,':'+tsp[1]);
				}
				selector=selector.substr(ts.length+1,selector.length);
			}
			else if(fc=='.')
			{
				var tsp=ts.split(/\:/);
				result=this.byClassName(tarr,tsp[0].replace('.',''));
				if(tsp[1])
				{
					result=this.filter(result,':'+tsp[1]);
				}
				selector=selector.substr(ts.length+1,selector.length);
			}
			else
			{
				if(fc==':' && (/^\:\[(.+)\]$/.test(ts) || /^(\:)(\w+)(\((.+)\)){0,1}$/.test(ts)))
				{
					result=this.filter(tarr,ts);
					selector=selector.substr(ts.length+1,selector.length);
				}
				else
				{
					var tsp=ts.split(':');
					result=this.byTag(tarr,tsp[0]);
					if(tsp[1])
					{
						result=this.filter(result,':'+tsp[1]);
					}
					selector=selector.substr(ts.length+1,selector.length);/////////就是这儿了
				}
			}
			selector=this.trim(selector);
			
			if(!JBF.isEmpty(selector))
			{
				if(mc==',')
				{
					tarr=[];
					var sp=oriselector.split(',');
					JBF.each(sp,function(v)
					{
						tarr=tarr.concat(this.find(v,context,true));
					},this);
					result=tarr;
				}
				else if(mc==' ')
				{
					tarr=[];
					JBF.each(result,function(n)
					{
						tarr=tarr.concat(this.dbChildren(n));
					},this);
					
					result=this.find(selector,tarr);
				}
				else if(mc=='>')
				{
					tarr=[];
					JBF.each(result,function(n)
					{
						tarr=tarr.concat(this.children(n));
					},this);
					result=this.find(selector,tarr);
				}
				else if(mc=='<')
				{
					tarr=[];
					JBF.each(result,function(n)
					{
						tarr=tarr.concat(this.parent(n));
					},this);
					result=this.find(selector,tarr);
				}
				else if(mc=='+')
				{
					tarr=[];
					JBF.each(result,function(n)
					{
						tarr=tarr.concat(this.next(n));
					},this);
					result=this.find(selector,tarr);
				}
				else if(mc=='-')
				{
					tarr=[];
					JBF.each(result,function(n)
					{
						tarr=tarr.concat(this.prev(n));
					},this);
					result=this.find(selector,tarr);
				}
			}
			return result;
		}
		
		return [];
	},
	
	exitst:function(list,val)
	{
		for(var i=0;i<list.length;i++)
		{
			if(list[i]==val)
				return true;
		}
		return false;
	},
	trim:function(s)
	{
		if(typeof s !='string') return;
		return s.replace(/(^\s*)|(\s*$)/g, '');
	},
	//检索指定的首个子节点
	child:function(n)
	{
        n = n.firstChild;
        while(n)
		{
            if(n.nodeType == 1)
               return n;
            n = n.nextSibling;
        }
        return null;
    },
	//检索指定的父节点
	parent:function(n)
	{
        n = n.parentNode;
        if(n.nodeType == 1)
			return n;
        return null;
    },
	//检索给定节点的弟节点
	next:function(n)
	{	
        while((n = n.nextSibling) && n.nodeType != 1);
        return n;
    },
	//检索给定节点的兄节点
	prev:function(n)
	{
        while((n = n.previousSibling) && n.nodeType != 1);
        return n;
    },
	//检索给定节点的所子节点
	//不包含孙节点,该列表也不包含无效的空节点
	children:function(n)
	{
		var nodeList=[];
		n = n.firstChild
		while(n)
		{
			if(n.nodeType==1)//可能需要加上空验证
				nodeList.push(n);
			n = n.nextSibling;
		}
		return nodeList;
    },
	//检索给定节点的子孙节点
	//该列表也不包含无效的空节点
	dbChildren:function(n)
	{
		var nodeList=this.children(n);
			
		for(var i=0;i<nodeList.length;i++)
		{
			nodeList=nodeList.concat(this.dbChildren(nodeList[i]))
		}
		return nodeList;
    },
	filter:function(nl,m)
	{
		var match=/^\:\[(.+)\]$/.exec(m);
		if(match && match[1])
		{
			return this.pseudo['attr'](nl,match[1]);
		}
		match=/^(\:)(\w+)(\(((\w+)|((\w+)~(\w+)))\)){0,1}$/.exec(m);
		if(match && match[2])
		{
			if(match[2] && match[7] && match[8])
			{
				return this.byPseudo(match[2])(nl,match[7],match[8]);	
			}
			else if(match[2] && match[6])
			{
				return this.byPseudo(match[2])(nl,match[6]);	
			}
			else
			{
				if('|text|password|radio|checkbox|submit|image|reset|button|file|'.indexOf(m[2].toLowerCase())>-1)
				{
					return this.byPseudo('attr')(nl,'type='+m[2].toLowerCase());
				}
				//这儿需要扩展为所有HTML标签
				else if('|input|select|textarea|div|p|table|tr|td|ul|li|a|b|frameset|frame|iframe|script|'.indexOf(m[2].toLowerCase())>-1)
				{
					return this.byTag(nl,m[2]);
				}
				/*else if('|even|odd|first|last|eq|'.indexOf(m[2].toLowerCase())>-1)
				{
					return this.byPseudo(m[2])(nl,m[5]);
				}*/
			}
			
		}
	},
	byId:function(nl,id)
	{
		var result=[];
		for(var i=0;i<nl.length;i++)
		{
			if(nl[i] && nl[i].id==id)
				result.push(nl[i]);
		}
		return result;
	},
	
	byTag:function(nl,tag)
	{
		var result=[];
		tag = tag.toLowerCase();
		for(var i=0;i<nl.length;i++)
		{
			if(nl[i] && nl[i].tagName.toLowerCase() ==tag)
				result.push(nl[i]);
		}
		return result;
	},
	byClassName:function(nl,cls)
	{
		var result=[];
		tag = tag.toLowerCase();
		for(var i=0;i<nl.length;i++)
		{
			if(nl[i] && this.exitst(nl[i].className.split(/\s/),cls))
				result.push(nl[i]);
		}
		return result;
	},
	
	//operators are =,!=,^=,$= ,!,|,&
	byAttr:function(nl,rules)
	{
		var result=[],
			spr='___JBFVAR___',
			ops=[],
			exps='',
			ts,
			vars=[],
			exitst=this.exitst;
		//转换表达式
		var cvt=function(_s,_m,_v,_vs)
		{
			_m=/^(\!){0,1}((\w+)|(\w+)(=|\!=|\^=|\$=|\*=|\$=){0,2}(\w*))$/.exec(_s);
			if(!_m)
				return;
			
			if(_m[4] && _m[5] && _m[6])
			{
				var a=spr+_m[4],
					b=_m[5],
					c='"'+_m[6]+'"';
				_v=a;
				if(b=='=')
				{
					_vs=a+b+'='+c;
				}
				else if(b=='!=')
				{
					_vs=a+b+c;
				}
				else if(b=='^=')
				{
					_vs=a+'.indexOf('+c+')==0';
				}
				else if(b=='$=')
				{
					_vs=a+'.substr('+a+'.lastIndexOf('+c+'),'+a+'.length)=='+b;
				}
				else if(b=='^=')
				{
					_vs=a+'.indexOf('+c+')>-1';
				}
			}
			else if(_m[3])
			{
				_v=spr+_m[3];
				_vs=_v;
			}
			if(!exitst(vars,_v))
			{
				vars.push(_v);
			}
			return (_m[1]||'')+_vs;
		}
		
		//连接多个表达式
		var rarr=rules.split(/\&|\|/);
		for(var i=0;i<rarr.length;i++)
		{
			if(rarr[i].length>0)
			{
				exps+=cvt(rarr[i])+rules.substr(rarr[i].length,1).replace('|',' || ').replace('&',' && ');
				rules=rules.substr(rarr[i].length+1,rules.length);
			}
		}
		var fk=function(_s)
		{
			//_s=trim(_s);
			if(!JBF.isEmpty(_s))
			{
				return _s;
			}
			return false;
		}
		JBF.each(nl,function(n)
		{
			if(n.nodeType)
			{
				JBF.each(vars,function(_a)
				{
					ts=_a+'=fk(n.getAttribute("'+_a.replace(spr,'')+'"))';
					
					if(!exitst(vars,ts))
						ops.push(ts);
					
				});
				if(ops.length>0)
				{
					eval('var '+ops.join(',') +';');
				}
				eval('if('+exps+'){result.push(n)}');
			}
		});
		
		return result;
		
		
	},
	
	byPseudo:function(type)
	{
		var me=this;
		switch(type)
		{
			case 'even' : 
				return function(nl)
				{
					var result=[];
					for(var i=0;i<nl.length;i++)
					{
						if(i!=0 && i%2==0)
							result.push(nl[i]);
					}
					return result;
				};
			case'odd':
				return function(nl)
				{
					var result=[];
					for(var i=0;i<nl.length;i++)
					{
						if(i==0 || i%2!=0)
							result.push(nl[i]);
					}
					return result;
				};
			case'eq':
				return function(nl,i)
				{
					i=parseInt((i+'').replace('min','0').replace('max',nl.length-1+''));
					return [nl[i]||[]];	
				};
			case 'lmt':
				return function(nl,s,e)
				{
					var result=[];
					s=parseInt((s+'').replace('min','0'));
					e=parseInt((e+'').replace('max',nl.length-1+''));
					for(var i=0;i<nl.length;i++)
					{
						if(i>=s && i<=e)
							result.push(nl[i]);
					}
					return result;
				};
			case'first':
				return function(nl)
				{
					return [nl[0]||[]];	
				};
			case 'last':
				return function(nl)
				{
					return [nl[nl.length-1]||[]];	
				};
			case 'attr':
				return function(nl,rules)
				{
					return me.byAttr(nl,rules);
				};
			default:
				return function(){alert('pseudo '+type)};
			
		}
	}
}
//转换为类
JBF.DomQuery=JBF.DomQuery.fn.toClass();







